﻿namespace SharpF2.Components
{
	using System;
	using System.Collections;
	using System.Text;
	using System.Text.RegularExpressions;
	using System.Windows.Controls;
	using System.Windows.Input;

	/// <summary>
	/// Interaction logic for TextBoxIntelliSense
	/// </summary>
	public class TextBoxIntelliSense : TextBox
	{
		#region Private Attributes

		private readonly Regex regex = new Regex("{|}", RegexOptions.Compiled);

		private Int32 CtrlSpaceSelectionLength;
		private Int32 CtrlSpaceSelectionStart;
		private String ctrlSpaceTextInput;
		private String CtrlSpaceTextInputPattern = String.Empty;
		private IEnumerable jumpKeyWords;

		#endregion

		#region Public Properties

		public String CtrlSpaceTextInput
		{
			get { return ctrlSpaceTextInput; }
			set
			{
				ctrlSpaceTextInput = value;
				var ids = regex.Split(ctrlSpaceTextInput);

				var position = 0;
				CtrlSpaceSelectionStart = 0;
				var CtrlSpaceSelectionEnd = 0;
				var sb = new StringBuilder();
				foreach (var item in ids)
				{
					switch (item)
					{
						case "SelectionStartPosition":
							CtrlSpaceSelectionStart = position;
							break;
						case "SelectionEndPosition":
							CtrlSpaceSelectionEnd = position;
							break;
						case "OpenCurlyBraces":
							position += 1;
							sb.Append("{");
							break;
						case "CloseCurlyBraces":
							position += 1;
							sb.Append("}");
							break;
						default:
							position += item.Length;
							sb.Append(item);
							break;
					}
				}

				CtrlSpaceSelectionLength = ((CtrlSpaceSelectionEnd - CtrlSpaceSelectionStart) > 0)
				                           	?
				                           		CtrlSpaceSelectionEnd - CtrlSpaceSelectionStart
				                           	:
				                           		0;
				CtrlSpaceTextInputPattern = sb.ToString();
			}
		}

		public IEnumerable JumpKeyWords
		{
			get { return jumpKeyWords; }
			set { jumpKeyWords = value; }
		}

		#endregion

		#region Protected Members

		protected override void OnKeyDown(KeyEventArgs e)
		{
			base.OnKeyDown(e);

			if (Key.Space.Equals(e.Key) && ModifierKeys.Control.Equals(Keyboard.Modifiers))
			{
				e.Handled = true;
				var futureSelectionStart = SelectionStart;
				var futureText = Text.Remove(SelectionStart, SelectionLength);
				Text = futureText.Insert(futureSelectionStart, CtrlSpaceTextInputPattern);
				SelectionStart = futureSelectionStart + CtrlSpaceSelectionStart;
				SelectionLength = CtrlSpaceSelectionLength;
			}
			else if (Key.Tab.Equals(e.Key) && ModifierKeys.Shift.Equals(Keyboard.Modifiers))
			{
				e.Handled = true;
				if (null == jumpKeyWords) return;

				var nextKeyWord = Int32.MinValue;
				foreach (var item in jumpKeyWords)
				{
					var keyWord = item.ToString();
					var nextPosition = 0;
					if (SelectionStart - 1 > 0)
						nextPosition = Text.LastIndexOf(keyWord, SelectionStart - 1);
					var nextPositionEnd = -1;
					if (SelectionStart - 1 - keyWord.Length > 1)
						nextPositionEnd = Text.LastIndexOf(keyWord, SelectionStart - 1 - keyWord.Length) + keyWord.Length;

					if (0 <= (nextPositionEnd - keyWord.Length))
					{
						if (-1 == nextPosition)
							nextPosition = nextPositionEnd;

						if (0 <= nextPosition && nextPosition < nextPositionEnd)
							nextPosition = nextPositionEnd;
					}
					if (0 <= nextPosition && nextKeyWord < nextPosition)
						nextKeyWord = nextPosition;
				}

				if (Int32.MinValue.Equals(nextKeyWord))
					nextKeyWord = 0;

				SelectionStart = nextKeyWord;
				SelectionLength = 0;
			}
			else if (Key.Tab.Equals(e.Key))
			{
				e.Handled = true;

				if (null == jumpKeyWords) return;
				if (SelectionStart + 1 > Text.Length) return;

				var nextKeyWord = Int32.MaxValue;
				foreach (var item in jumpKeyWords)
				{
					var keyWord = item.ToString();
					var nextPosition = Text.IndexOf(keyWord, SelectionStart + 1);
					var nextPositionEnd = Text.IndexOf(keyWord, SelectionStart) + keyWord.Length;

					if (-1 != (nextPositionEnd - keyWord.Length))
					{
						if (-1 == nextPosition)
							nextPosition = nextPositionEnd;

						if (-1 != nextPosition && nextPosition > nextPositionEnd)
							nextPosition = nextPositionEnd;
					}

					if (-1 != nextPosition && nextKeyWord > nextPosition)
						nextKeyWord = nextPosition;
				}

				if (Int32.MaxValue.Equals(nextKeyWord))
					nextKeyWord = SelectionStart;

				SelectionStart = nextKeyWord;
				SelectionLength = 0;
			}
		}

		#endregion
	}
}